#include "mqtt.h"


pthread_mutex_t protocol_mutex = PTHREAD_MUTEX_INITIALIZER;
extern char *mac_ptr;
extern char mac_buf[6];
extern struct sockaddr_in* global_client_addr;
extern uint16_t tmp_seq;
extern sqlite3 *fsl_db;
uint16_t enter_thread_time = 0;
MQTTClient client;


char topic_usr_get[50] = {};
char topic_list_project[50] = {};
char topic_list_device[50] = {};
char topic_Control_device[50] = {};
char topic_Status_Device[50] = {};


pthread_mutex_t mqtt_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t mqtt_cond = PTHREAD_COND_INITIALIZER;
int msg_received = 0;

mqtt_message_t mqtt_msg_received;

// 把 . 换成 /
void replace_dots_with_slashes(char* str) 
{
    for (char* p = str; *p != '\0'; ++p) 
    {
        if (*p == '.') 
        {
            *p = '/';
        }
    }
}

void* mqtt_message_handler_thread(void* arg) 
{
    (void)arg;

    while (1) 
    {
        pthread_mutex_lock(&mqtt_lock);
        while (!msg_received) 
        {
            pthread_cond_wait(&mqtt_cond, &mqtt_lock);
        }

        // 每收到一条mqtt消息，就加一，防止seq重复使用
        enter_thread_time++;

        // 立即持有主线程的锁，避免主线程竞争相同的资源
        pthread_mutex_lock(&protocol_mutex);

        mqtt_message_t thread_local_message;
        memcpy(&thread_local_message, &mqtt_msg_received, sizeof(mqtt_message_t));
        printf("message: %.*s\n", thread_local_message.payloadlen, (char *)thread_local_message.payload);

        msg_received = 0;
        
        pthread_mutex_unlock(&mqtt_lock);

        // 解析JSON 字符串
        cJSON *json = cJSON_Parse(thread_local_message.payload);
        if (json == NULL) 
        {
            FSL_LOG("[mqtt_message_handler_thread] Error parsing JSON");
            continue;
        }
        
        // 把action 字段取出来
        cJSON *action = cJSON_GetObjectItem(json, "action");
        if (cJSON_IsString(action) && (action->valuestring != NULL))
        {
            // FSL_LOG("MQTT Get Action: %s", action->valuestring);

            // 组装action 主题
            char action_with_slashes[128];
            action_with_slashes[0] = '/';
            strncpy(action_with_slashes + 1, action->valuestring, sizeof(action_with_slashes) - 2);
            action_with_slashes[sizeof(action_with_slashes) - 1] = '\0'; 

            replace_dots_with_slashes(action_with_slashes);

            // 对比
            if (strcmp(action_with_slashes, FSL_Mqtt_Control_Device) == 0) 
            {
                FSL_Mqtt_Handle_Control_Device(json);

                goto end;
            } 
            else if (strcmp(action_with_slashes, FSL_Mqtt_Modify_Device) == 0) 
            {
                printf("Handling modify device action\n");
                goto end;
            } 
            else 
            {
                printf("Unknown action: %s\n", action_with_slashes);
                goto end;
            }
        }
        else 
        {
            printf("No valid 'action' field found in JSON\n");
            goto end;
        }

end:
    cJSON_Delete(json);
    // 释放主线程的锁
    pthread_mutex_unlock(&protocol_mutex);


    }
    return NULL;
}


int msg_arrive(void *context, char *topicName, int topicLen, MQTTClient_message *message) 
{
    // printf("%s     topic: %s\n", TAG, topicName);
    // printf("%s   message: %.*s\n", TAG, message->payloadlen, (char *)message->payload);
    (void)context;
    (void)topicLen;

    pthread_mutex_lock(&mqtt_lock);

    if (message->payloadlen >= MAX_MQTT_PAYLOAD_SIZE) 
    {
        fprintf(stderr, "[MQTT_msg_arrive] Payload size is too large: %d\n", message->payloadlen);
        pthread_mutex_unlock(&mqtt_lock);
        return 0;
    }

    // 拷贝mqtt消息的内容
    mqtt_msg_received.payloadlen = message->payloadlen;
    memcpy(mqtt_msg_received.payload, (char *)message->payload, message->payloadlen);
    mqtt_msg_received.payload[message->payloadlen] = '\0';

    msg_received = 1;

    pthread_cond_signal(&mqtt_cond);
    pthread_mutex_unlock(&mqtt_lock);


    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);

    return 1;
}


void FLS_Topic_Pingjie(void)
{
    sprintf(topic_usr_get, "%s%s", mac_ptr, FSL_Mqtt_Get);
    sprintf(topic_list_project, "%s%s", mac_ptr, FSL_Mqtt_List_Project);
    sprintf(topic_list_device, "%s%s", mac_ptr, FSL_Mqtt_List_Device);
    sprintf(topic_Control_device, "%s%s", mac_ptr, FSL_Mqtt_Control_Device);
    sprintf(topic_Status_Device, "%s%s", mac_ptr, FSL_Mqtt_Status_Device);
}


void json_test(MQTTClient client, MQTTClient_deliveryToken token)
{
    // 创建JSON对象
    cJSON *root = cJSON_CreateObject();

    // 添加seq字段
    cJSON_AddStringToObject(root, "seq", "");

    // 添加time字段
    cJSON_AddStringToObject(root, "time", "2022-11-24T08:21:34.000Z");

    // 添加action字段
    cJSON_AddStringToObject(root, "action", "hz.list.project");

    // 创建params对象
    cJSON *params = cJSON_CreateObject();

    // 添加id字段
    cJSON_AddStringToObject(params, "id", "");

    // 创建filter数组
    cJSON *filter = cJSON_CreateArray();
    cJSON_AddItemToObject(params, "filter", filter);

    // 创建config数组
    cJSON *config = cJSON_CreateArray();
    cJSON_AddItemToObject(params, "config", config);

    // 创建config中的对象
    cJSON *config_item = cJSON_CreateObject();
    cJSON_AddItemToArray(config, config_item);

    // 添加config中的字段
    cJSON_AddStringToObject(config_item, "CF_ProjectId", "");
    cJSON_AddStringToObject(config_item, "CF_ProjectName", "");

    // 将params对象添加到root对象中
    cJSON_AddItemToObject(root, "params", params);

    // 将JSON对象转换为字符串
    char *json_str = cJSON_Print(root);

    // 输出JSON字符串
    printf("%s\n", json_str);


    MQTTClient_message pubmsg = MQTTClient_message_initializer;
    pubmsg.payload = json_str;
    pubmsg.payloadlen = strlen(pubmsg.payload);
    pubmsg.qos = QOS;
    pubmsg.retained = 0;
    MQTTClient_publishMessage(client, topic_list_project, &pubmsg, &token);


    // 释放内存
    cJSON_Delete(root);
    free(json_str);
}

// 处理MQTT 的 “hz.control.device” 设备控制的消息
void FSL_Mqtt_Handle_Control_Device(cJSON *json )
{
    cJSON *params = cJSON_GetObjectItem(json, "params");
    if (params) 
    {
        cJSON *config_array = cJSON_GetObjectItem(params, "config");
        if (cJSON_IsArray(config_array)) 
        {
            int config_array_size = cJSON_GetArraySize(config_array);
            for (int i = 0; i < config_array_size; ++i) 
            {
                cJSON *config_item = cJSON_GetArrayItem(config_array, i);
                if (cJSON_IsObject(config_item)) 
                {
                    cJSON *cf_radar_bright_setting = cJSON_GetObjectItem(config_item, "CF_RadarBrightSetting");
                    cJSON *cf_on_off = cJSON_GetObjectItem(config_item, "CF_OnOff");
                    cJSON *CF_Bright = cJSON_GetObjectItem(config_item, "CF_Bright");
                    cJSON *id = cJSON_GetObjectItem(params, "id");

                    if (cJSON_IsString(id) && (id->valuestring != NULL)) 
                    {
                        const char *shortaddr = (const char *)id->valuestring;
                        uint16_t m_shortaddr = (uint16_t)atoi(shortaddr);
                        // 三段亮度设置
                        if (cf_radar_bright_setting) 
                        {

                            cJSON *one_brightness = cJSON_GetObjectItem(cf_radar_bright_setting, "oneBrightness");
                            cJSON *one_brightness_time = cJSON_GetObjectItem(cf_radar_bright_setting, "oneBrightnessTime");
                            cJSON *two_brightness = cJSON_GetObjectItem(cf_radar_bright_setting, "twoBrightness");
                            cJSON *two_brightness_time = cJSON_GetObjectItem(cf_radar_bright_setting, "twoBrightnessTime");
                            cJSON *three_brightness = cJSON_GetObjectItem(cf_radar_bright_setting, "threeBrightness");
                            cJSON *radar_switch = cJSON_GetObjectItem(cf_radar_bright_setting, "radarSwitch");

                            uint8_t sensor_switch = (uint8_t)atoi(radar_switch->valuestring);
                            uint8_t brightness_h = (uint8_t)atoi(one_brightness->valuestring);
                            uint16_t cf_bright_h_delay = (uint16_t)atoi(one_brightness_time->valuestring);
                            uint8_t brightness_lowest = (uint8_t)atoi(three_brightness->valuestring);
                            uint8_t brightness_middle = (uint8_t)atoi(two_brightness->valuestring);
                            uint16_t brightness_middle_delay_time = (uint16_t)atoi(two_brightness_time->valuestring);

    // printf("sensor_switch: %u\n", sensor_switch);
    // printf("brightness_h: %u\n", brightness_h);
    // printf("cf_bright_h_delay: %u\n", cf_bright_h_delay);
    // printf("brightness_lowest: %u\n", brightness_lowest);
    // printf("brightness_middle: %u\n", brightness_middle);
    // printf("brightness_middle_delay_time: %u\n", brightness_middle_delay_time);


FSL_Set_Park_Area_Sensor(++tmp_seq, global_client_addr, m_shortaddr, 0, DWORD_BYTE_DIVIDE_H4(m_shortaddr), 
                        sensor_switch, brightness_h, cf_bright_h_delay, brightness_lowest, brightness_middle, brightness_middle_delay_time);

                            return;
                        }
                        // 开关
                        else if(cf_on_off)
                        {
                            // FSL_LOG("CF_OnOff found in config !!!!");

                            // 操作短地址
                            FSL_Short_Adress_Control(++tmp_seq, global_client_addr, m_shortaddr, atoi(cf_on_off->valuestring), 50);
                            char sql[128];
                            // 更新数据库
                            sprintf(sql, "UPDATE %s SET CF_OnOff = %d , CF_Bright = %d WHERE shortaddr = '%s';", Device_List_Table, atoi(cf_on_off->valuestring), 50, shortaddr);
                            sqlite3_exec(fsl_db, sql, 0, 0, 0);

                            return;
                        }
                        // 亮度
                        else if(CF_Bright)
                        {
                            uint8_t brightness = CF_Bright->valueint;
                            char sql[128];
                            if(brightness)
                                FSL_Short_Adress_Control(++tmp_seq, global_client_addr, m_shortaddr, 1, brightness);
                            else
                                FSL_Short_Adress_Control(++tmp_seq, global_client_addr, m_shortaddr, 0, brightness);

                            sprintf(sql, "UPDATE %s SET CF_OnOff = %d, CF_Bright = %d WHERE shortaddr = '%s';", Device_List_Table, brightness > 0 ? 1 : 0,brightness, shortaddr);
                            sqlite3_exec(fsl_db, sql, 0, 0, 0);

                            return;
                        }
                    }
                }
            }
        }
    }
}

// 设备状态上报
void FSL_Mqtt_Report(const char *shortaddr)
{
    sqlite3_stmt *stmt;

    char *sql = "SELECT CF_DeviceId, CF_DeviceName, CF_ProductId, CF_ProjectId, CF_SpaceId, "
            "CF_RegionId, CF_GroupIds, CF_EnergyCost, CF_CurrentEnergyCost, CF_EnergyCostDict, "
            "CF_Power, CF_WorkDuration, CF_Mac, CF_Version, CF_OnOff, CF_Flash, CF_Bright, "
            "CF_RadarBrightSetting, CF_RadarTimerOnOff, CF_RadarTimerSetting, CF_GatewayId, "
            "CF_TriggerCount, CF_LastUpdateTime, CF_ReportTime FROM sta_device WHERE shortaddr = ?";


    // 准备SQL语句
    int rc = sqlite3_prepare_v2(fsl_db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) 
    {
        fprintf(stderr, "[FSL_Mqtt_Report] Failed to prepare statement: %s\n", sqlite3_errmsg(fsl_db));
    }

    // 绑定参数
    sqlite3_bind_text(stmt, 1, shortaddr, -1, SQLITE_STATIC);

    // 执行查询
    rc = sqlite3_step(stmt);
    if (rc == SQLITE_ROW) 
    {
        const unsigned char *CF_DeviceId = sqlite3_column_text(stmt, 0);
        const unsigned char *CF_DeviceName = sqlite3_column_text(stmt, 1);
        int CF_ProductId = sqlite3_column_int(stmt, 2);
        int CF_ProjectId = sqlite3_column_int(stmt, 3);
        int CF_SpaceId = sqlite3_column_int(stmt, 4);
        int CF_RegionId = sqlite3_column_int(stmt, 5);
        const unsigned char *CF_GroupIds = sqlite3_column_text(stmt, 6);
        const unsigned char *CF_EnergyCost = sqlite3_column_text(stmt, 7);
        const unsigned char *CF_CurrentEnergyCost = sqlite3_column_text(stmt, 8);
        const unsigned char *CF_EnergyCostDict = sqlite3_column_text(stmt, 9);
        int CF_Power = sqlite3_column_int(stmt, 10);
        int CF_WorkDuration = sqlite3_column_int(stmt, 11);
        const unsigned char *CF_Mac = sqlite3_column_text(stmt, 12);
        const unsigned char *CF_Version = sqlite3_column_text(stmt, 13);
        int CF_OnOff = sqlite3_column_int(stmt, 14);
        const unsigned char *CF_Flash = sqlite3_column_text(stmt, 15);
        int CF_Bright = sqlite3_column_int(stmt, 16);
        const unsigned char *CF_RadarBrightSetting = sqlite3_column_text(stmt, 17);
        const unsigned char *CF_RadarTimerOnOff = sqlite3_column_text(stmt, 18);
        const unsigned char *CF_RadarTimerSetting = sqlite3_column_text(stmt, 19);
        const unsigned char *CF_GatewayId = sqlite3_column_text(stmt, 20);
        int CF_TriggerCount = sqlite3_column_int(stmt, 21);
        const unsigned char *CF_LastUpdateTime = sqlite3_column_text(stmt, 22);
        const unsigned char *CF_ReportTime = sqlite3_column_text(stmt, 23);

        // 创建JSON对象
        cJSON *root = cJSON_CreateObject();
        cJSON *data = cJSON_CreateObject();
        cJSON *config = cJSON_CreateArray();
        cJSON *config_item;

        // 添加顶层属性
        cJSON_AddStringToObject(root, "seq", "");
        cJSON_AddStringToObject(root, "time", "");
        cJSON_AddStringToObject(root, "action", "hz.status.device");
        cJSON_AddStringToObject(root, "status", "success");
        cJSON_AddStringToObject(root, "msg", "");

        // 添加 data 下的“id” 对象
        cJSON_AddStringToObject(data, "id", shortaddr);

        // 添加 config 数组
        config_item = cJSON_CreateObject();
        cJSON_AddNumberToObject(config_item, "CF_Bright", CF_Bright);
        cJSON_AddStringToObject(config_item, "CF_DeviceId", (const char *)CF_DeviceId);
        cJSON_AddStringToObject(config_item, "CF_DeviceName", (const char *)CF_DeviceName);
        cJSON_AddNumberToObject(config_item, "CF_ProductId", CF_ProductId);
        cJSON_AddNumberToObject(config_item, "CF_ProjectId", CF_ProjectId);
        cJSON_AddNumberToObject(config_item, "CF_SpaceId", CF_SpaceId);
        cJSON_AddNumberToObject(config_item, "CF_RegionId", CF_RegionId);
        cJSON_AddStringToObject(config_item, "CF_GroupIds", (const char *)CF_GroupIds);
        cJSON_AddStringToObject(config_item, "CF_EnergyCost", (const char *)CF_EnergyCost);
        cJSON_AddStringToObject(config_item, "CF_CurrentEnergyCost", (const char *)CF_CurrentEnergyCost);
        cJSON_AddStringToObject(config_item, "CF_EnergyCostDict", (const char *)CF_EnergyCostDict);
        cJSON_AddNumberToObject(config_item, "CF_Power", CF_Power);
        cJSON_AddNumberToObject(config_item, "CF_WorkDuration", CF_WorkDuration);
        cJSON_AddStringToObject(config_item, "CF_Mac", (const char *)CF_Mac);
        cJSON_AddStringToObject(config_item, "CF_Version", (const char *)CF_Version);
        cJSON_AddNumberToObject(config_item, "CF_OnOff", CF_OnOff);
        cJSON_AddStringToObject(config_item, "CF_Flash", (const char *)CF_Flash);
        cJSON_AddStringToObject(config_item, "CF_RadarBrightSetting", (const char *)CF_RadarBrightSetting);
        cJSON_AddStringToObject(config_item, "CF_RadarTimerOnOff", (const char *)CF_RadarTimerOnOff);
        cJSON_AddStringToObject(config_item, "CF_RadarTimerSetting", (const char *)CF_RadarTimerSetting);
        cJSON_AddStringToObject(config_item, "CF_GatewayId", (const char *)CF_GatewayId);
        cJSON_AddNumberToObject(config_item, "CF_TriggerCount", CF_TriggerCount);
        cJSON_AddStringToObject(config_item, "CF_LastUpdateTime", (const char *)CF_LastUpdateTime);
        cJSON_AddStringToObject(config_item, "CF_ReportTime", (const char *)CF_ReportTime);

        // 将config_item添加到config数组中
        cJSON_AddItemToArray(config, config_item);
        
        // 将config数组添加到data对象中
        cJSON_AddItemToObject(data, "config", config);

        // 将data对象添加到根对象中
        cJSON_AddItemToObject(root, "data", data);

        // 将JSON对象转换为字符串
        char *payload = cJSON_Print(root);
        if (payload == NULL) 
        {
            fprintf(stderr, "[FSL_Mqtt_Report] Failed to print JSON.\n");
            cJSON_Delete(root);
        }

        // 打印JSON字符串（可选）
        printf("Payload: %s\n", payload);


        // 打印变量值
        // printf("CF_DeviceId: %s\n", CF_DeviceId);
        // printf("CF_DeviceName: %s\n", CF_DeviceName);
        // printf("CF_ProductId: %d\n", CF_ProductId);
        // printf("CF_ProjectId: %d\n", CF_ProjectId);
        // printf("CF_SpaceId: %d\n", CF_SpaceId);
        // printf("CF_RegionId: %d\n", CF_RegionId);
        // printf("CF_GroupIds: %s\n", CF_GroupIds);
        // printf("CF_EnergyCost: %s\n", CF_EnergyCost);
        // printf("CF_CurrentEnergyCost: %s\n", CF_CurrentEnergyCost);
        // printf("CF_EnergyCostDict: %s\n", CF_EnergyCostDict);
        // printf("CF_Power: %d\n", CF_Power);
        // printf("CF_WorkDuration: %d\n", CF_WorkDuration);
        // printf("CF_Mac: %s\n", CF_Mac);
        // printf("CF_Version: %s\n", CF_Version);
        // printf("CF_OnOff: %d\n", CF_OnOff);
        // printf("CF_Flash: %s\n", CF_Flash);
        // printf("CF_Bright: %d\n", CF_Bright);
        // printf("CF_RadarBrightSetting: %s\n", CF_RadarBrightSetting);
        // printf("CF_RadarTimerOnOff: %s\n", CF_RadarTimerOnOff);
        // printf("CF_RadarTimerSetting: %s\n", CF_RadarTimerSetting);
        // printf("CF_GatewayId: %s\n", CF_GatewayId);
        // printf("CF_TriggerCount: %d\n", CF_TriggerCount);
        // printf("CF_LastUpdateTime: %s\n", CF_LastUpdateTime);
        // printf("CF_ReportTime: %s\n", CF_ReportTime);
    } else 
    {
        fprintf(stderr, "[FSL_Mqtt_Report] No data found for shortaddr: %s\n", shortaddr);
    }

    // 清理并关闭数据库
    sqlite3_finalize(stmt);
}

void FSL_Mqtt_Init(void)
{
    FLS_Topic_Pingjie();

    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    // MQTTClient_message pubmsg = MQTTClient_message_initializer;
    // MQTTClient_deliveryToken token;
    MQTTClient_SSLOptions ssl_opts = MQTTClient_SSLOptions_initializer;

    int rc;

    MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
    
    conn_opts.ssl= &ssl_opts;
    conn_opts.username = USERNAME;
    conn_opts.password = PASSWORD;
    conn_opts.keepAliveInterval = 20;
    conn_opts.cleansession = 1;    // 设置连接选项中的清除会话标志

    // 设置消息到达和消息传递回调函数
    MQTTClient_setCallbacks(client, NULL, NULL, msg_arrive, NULL);


    if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
    {
        FSL_LOG("Failed to connect to MQTT server, return code %d",rc);
        exit(-1);
    }
    else
        FSL_LOG("Connected to MQTT server");

    // 发布消息
    // pubmsg.payload = "Hello, FSL!";
    // pubmsg.payloadlen = strlen(pubmsg.payload);
    // pubmsg.qos = QOS;
    // pubmsg.retained = 0;
    // MQTTClient_publishMessage(client, topic_list_device, &pubmsg, &token);


    // 订阅主题
    FSL_LOG("[FSL_Mqtt_Init] 订阅的 Topic is: %s\n", topic_usr_get);
    MQTTClient_subscribe(client, topic_usr_get, QOS);

    // 启动消息处理线程
    pthread_t handler_thread;
    pthread_create(&handler_thread, NULL, mqtt_message_handler_thread, NULL);


    return;
}


